﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Sinacor.Infra.Service.Validation;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Security.Authorization;
using System.Linq;

namespace Sinacor.Servico.Bovespa.Alocacao.BusinessLogic
{

	public class Recompra : BaseBusinessLogic
    {

        #region propriedades
        ResourceAccess.Recompra raRecompra = null;
        #endregion

        #region Construtores
        public Recompra()
        {
            raRecompra = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.Recompra();
        } 
		#endregion Construtores

		#region Métodos 
		/// <summary>
		/// Atualiza a composição financeira de uma recompra
		/// </summary>
		/// <param name="entity"></param>
		public void AtualizarComposicaoFinanceiraRecompra(BusinessEntity.ComposicaoFinanceiraRecompra entity)
        {
            //Verifica se parametro de entrada foi informado
            if (entity == null)
                throw new BusinessException(109648);

            //Validar permissão de acesso
            this.ValidarPermissaoExecucao();

            //Executar validação dos campos obrigatórios
            SinacorValidation validation = new SinacorValidation();
            validation.AddValidation<BusinessEntity.ComposicaoFinanceiraRecompra>(entity);
            validation.Validate();
            validation = null;

            //Atualizar composição financeira recompra
            raRecompra.AtualizarComposicaoFinanceiraRecompra(entity);

            //Executar o cálculo financeiro do cliente
            this.ExecutarCalculoFinanceiroCliente(
                new BusinessEntity.Parameter.FiltroExecucaoRecompra() 
                { 
                    CodigoCliente = entity.CodigoCliente.Value,
                    DataPregao = entity.DataMovimento.Value 
                });
		}

		/// <summary>
		/// Consulta uma lista de execuções de uma recompra
		/// </summary>
		/// <param name="entity"></param>
		public List<BusinessEntity.ExecucaoRecompra> ConsultarExecucoesRecompra(BusinessEntity.Parameter.FiltroRecompraChave entity, BusinessEntity.Recompra recompra)
        {
            BusinessEntity.Parameter.FiltroExecucaoRecompra filtro = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Parameter.FiltroExecucaoRecompra();

            //Verifica se parametro de entrada foi informado
            if (entity == null)
                throw new BusinessException(109648);

            //Validar permissão de acesso
            this.ValidarPermissaoExecucao();

            //Verifica se a data do negócio foi informada
            if (entity.DataNegocio.Equals(DateTime.MinValue))
                throw new BusinessException(109645);
            else if (entity.NumeroRecompra.Equals(0))
                throw new BusinessException(109647);

            if (recompra == null)
            {
                recompra = this.ObterRecompra(entity);
            }

            //Executar cálculo financeiro para o cliente da recompra
            filtro.DataNegocio = recompra.DataNegocio;
            filtro.CodigoCliente = recompra.CodigoCliente.Value;
            filtro.DataPregao = entity.DataPregao;
            this.ExecutarCalculoFinanceiroRecompra(filtro);

            //Gerar timestamp para identificador da transação
            DateTime timestamp = DateTime.Now;

            //Executar atualização dos custos da recompra
            filtro = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Parameter.FiltroExecucaoRecompra();
            filtro.NumeroRecompra = recompra.NumeroRecompra;
            filtro.DataNegocio = recompra.DataNegocio;
            filtro.DataSistema = timestamp;
            filtro.Estacao = AuthorizationContext.Current.ClientHost.Name;
            filtro.CodigoCliente = recompra.CodigoCliente.Value;
            filtro.DataPregao = entity.DataPregao;
            filtro.DataMovimento = new Movimento.BusinessLogic.ControleMovimentoOrdens().ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento()).DataMovimento;
            this.ExecutarAtualizacaoCustos(filtro);

            //Consultar as execuções da recompra
            filtro = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Parameter.FiltroExecucaoRecompra();
            filtro.NumeroRecompra = recompra.NumeroRecompra;
            filtro.DataNegocio = recompra.DataNegocio;
            filtro.DataSistema = timestamp;
            filtro.Estacao = AuthorizationContext.Current.ClientHost.Name;

            return (raRecompra.ConsultarExecucoesRecompra(filtro));

		}
		/// <summary>
		/// Consultar uma lista de falhas que originaram recompras conforme o filtro de
		/// pesquisa
		/// </summary>
		/// <param name="entity"></param>
		public List<BusinessEntity.FalhaRecompra> ConsultarFalhasRecompras(BusinessEntity.Parameter.FiltroFalhaRecompra entity)
        {
            List<BusinessEntity.FalhaRecompra> retorno = null;
            //Verifica se parametro de entrada foi informado
            if (entity == null)
                throw new BusinessException(109644);
            
            //Validar permissão de acesso
            this.ValidarPermissaoExecucao();

            if (entity.DataPregao.Equals(DateTime.MinValue))
                throw new BusinessException(109645);


            //Consultar falhas que originaram recompras
            retorno = raRecompra.ConsultarFalhasRecompras(entity);

            return retorno;
		}

		/// <summary>
		/// Consulta uma lista de recompras conforme o filtro de pesquisa
		/// </summary>
		/// <param name="entity"></param>
		public List<BusinessEntity.Recompra> ConsultarRecompras(BusinessEntity.Parameter.FiltroRecompra entity)
        {
            if (entity == null)
                throw new BusinessException(109648);
            else
            {
                this.ValidarPermissaoExecucao();
                return raRecompra.ConsultarRecompras(entity);
            }
		}

		/// <summary>
		/// Executa a atualização dos custos da operação de recompra
		/// </summary>
		/// <param name="entity"></param>
		private void ExecutarAtualizacaoCustos(BusinessEntity.Parameter.FiltroExecucaoRecompra entity)
        {
            BusinessEntity.Resultado resultado = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Resultado();
            resultado = raRecompra.ExecutarAtualizacaoCustos(entity);
            if (resultado.Sucesso == false)
            {
                if (resultado.CodigoErro.Equals(-1))
                    throw new BusinessException(109651);
                else
                    TratarExcecoes(resultado);
            }
		}

        /// <summary>
		/// Executa o cálculo financeiro para o cliente
		/// </summary>
		/// <param name="entity"></param>
		private void ExecutarCalculoFinanceiroCliente(BusinessEntity.Parameter.FiltroExecucaoRecompra entity)
        {
            BusinessEntity.Resultado resultado = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Resultado();

            resultado = raRecompra.ExecutarCalculoFinanceiroCliente(entity);
            if (resultado.Sucesso == false)
            {
                if (resultado.CodigoErro.Equals(-1))
                    throw new BusinessException(109649);
                else
                    TratarExcecoes(resultado);
            }

		}


		/// <summary>
		/// Executar cálculo financeiro antes da regularização para o cliente
		/// </summary>
		/// <param name="entity"></param>
		private void ExecutarCalculoFinanceiroRecompra(BusinessEntity.Parameter.FiltroExecucaoRecompra entity)
        {
            BusinessEntity.Resultado resultado = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Resultado();
            
            resultado = raRecompra.ExecutarCalculoFinanceiroRecompra(entity);
            if (resultado.Sucesso == false)
            {
                if (resultado.CodigoErro.Equals(-1))
                    throw new BusinessException(109649);
                else
                    TratarExcecoes(resultado);
            }
        }

        /// <summary>
        /// ObterComposicaoFinanceiraRecompra
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public BusinessEntity.ComposicaoFinanceiraRecompra ObterComposicaoFinanceiraRecompra(BusinessEntity.Parameter.FiltroRecompraChave entity)
        {
            //Verifica se o parametro de entrada foi informado
            if (entity == null)
                throw new BusinessException(109646);

            //Valida permissão para execução
            this.ValidarPermissaoExecucao();

            //Verifica se a data do negócio foi informada
            if (entity.DataNegocio.Equals(DateTime.MinValue))
                throw new BusinessException(109645);
            else if (entity.NumeroRecompra.Equals(0))
                throw new BusinessException(109647);

            //Obter composição financeira da recompra
            return (raRecompra.ObterComposicaoFinanceiraRecompra(entity));
        }

		/// <summary>
		/// Obtém um recompra conforme chave informada
		/// </summary>
		/// <param name="entity"></param>
		public BusinessEntity.Recompra ObterRecompra(BusinessEntity.Parameter.FiltroRecompraChave entity)
        {
            BusinessEntity.Recompra recompra = null;
            BusinessEntity.ValoresRecompra itemRecompra = null;

            //Verifica se o parametro de entrada foi informado
            if (entity == null)
                throw new BusinessException(109646);

            //Valida permissão para execução
            this.ValidarPermissaoExecucao();

            //Verifica se a data do negócio foi informada
            if (entity.DataNegocio.Equals(DateTime.MinValue))
                throw new BusinessException(109645);
            else if (entity.NumeroRecompra.Equals(0))
                throw new BusinessException(109647);

            //Obter recompra
            recompra = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Recompra();
            recompra = raRecompra.ObterRecompra(entity);

            if (recompra == null)
                throw new BusinessException(109722);
            else
            {
                //Consultar as execuções da recompra
                recompra.Execucoes = this.ConsultarExecucoesRecompra(entity, recompra);


                //Obter os valores das despesas cobradas 
                itemRecompra = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.ValoresRecompra();
                itemRecompra = raRecompra.ObterValoresDespesasFalha(entity);
                recompra.Valores = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.ValoresRecompra();
                recompra.Valores.DataNegocio = itemRecompra.DataNegocio;
                recompra.Valores.NumeroRecompra = itemRecompra.NumeroRecompra;
                recompra.Valores.ValorCorretagem = itemRecompra.ValorCorretagem;
                recompra.Valores.ValorEmolumentos = itemRecompra.ValorEmolumentos;
                recompra.Valores.ValorTaxaLiquidacao = itemRecompra.ValorTaxaLiquidacao;
                recompra.Valores.Volume = itemRecompra.Volume;

                //Obter composição financeira da recompra
                recompra.ComposicaoFinanceira = this.ObterComposicaoFinanceiraRecompra(entity);

                //Obter os valores das despesas cobradas 
                recompra.Valores = raRecompra.ObterValoresDespesasFalha(entity);

                //Obter composição financeira da recompra
                recompra.ComposicaoFinanceira = this.ObterComposicaoFinanceiraRecompra(entity);

                return recompra;
            }
		}

        /// <summary>
		/// Trata exceção gerada pelo oracle
		/// </summary>
		/// <param name="resultado"></param>
		private void TratarExcecoes(BusinessEntity.Resultado resultado)
        {
            if (string.IsNullOrEmpty(resultado.Argumentos))
                throw new BusinessException(resultado.CodigoErro);
            else
            {
                List<object> ret = ErrorMessage.ConvertXmlArgumentsToParameters(resultado.Argumentos);
                throw new BusinessException(resultado.CodigoErro, ret.ToArray());
            }
		}

		/// <summary>
		/// Valida se o usuário possui permissão para execução de ações neste contrato de
		/// serviços
		/// </summary>
		private void ValidarPermissaoExecucao()
        {
            //Validar permissão de execução
            bool retornoCheckUserAccess = AuthorizationContext.Current.CheckUserAccess("NEGO", "ORD") & AuthorizationContext.Current.CheckUserAccess("MNEG", "ORD");
            if (!retornoCheckUserAccess)
                throw new BusinessException(109587);

            //Obter informações sobre o movimento de ordens e verificar se está fechado
            Movimento.BusinessEntity.InformacoesMovimento informacoesMovimento = null;
            informacoesMovimento = new Movimento.BusinessLogic.ControleMovimentoOrdens().ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());
            if (informacoesMovimento != null &&
                informacoesMovimento.EstadoMovimento == Movimento.BusinessEntity.Enum.TipoMovimento.Fechado)
                throw new BusinessException(109650);
        } 
		#endregion Métodos 

	}

}